package com.sleepless.my.service.impl;

import com.sleepless.my.entity.UsersEntity;
import com.sleepless.my.io.RestBean;
import com.sleepless.my.io.request.User.LoginReq;
import com.sleepless.my.io.request.User.RegisterReq;
import com.sleepless.my.io.response.User.GetUserInfoResp;
import com.sleepless.my.io.response.User.LoginResp;
import com.sleepless.my.io.response.User.RegisterResp;
import com.sleepless.my.repository.UsersRepository;
import com.sleepless.my.service.UserService;
import com.sleepless.my.utils.FileUtil;
import com.sleepless.my.utils.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.AccessDeniedException;
import java.util.UUID;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private UsersRepository usersRespository;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private FileUtil fileUtil;

    public void handleLoginProcess(HttpServletRequest request,
                                          HttpServletResponse response,
                                          Object exceptionOrAuthentication) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        if(exceptionOrAuthentication instanceof AccessDeniedException exception) {
            writer.write(RestBean.serializeFailure(403, "拒绝访问"));
        } else if(exceptionOrAuthentication instanceof AuthenticationException exception) {
            writer.write(RestBean.serializeFailure(401, "账号或密码错误"));
        } else if(exceptionOrAuthentication instanceof Authentication authentication){
            //不过这里需要注意，在登录成功的时候需要返回我们生成的JWT令牌，这样客户端下次访问就可以携带这个令牌了，令牌过期之后就需要重新登录才可以
            Object principal = authentication.getPrincipal();
            if (principal instanceof UserDetails) {
                UserDetails userDetails = (UserDetails) principal;
                UsersEntity usersEntity = usersRespository.findByusername(userDetails.getUsername());
                writer.write(RestBean.serializeSuccess(
                        LoginResp.builder().token(JwtUtil.createJWT(JwtUtil.createClaims(usersEntity.getUsername()))).build()
                ));
            } else {
                writer.write(RestBean.serializeFailure(RestBean.Code.服务错误));
            }
        }
    }

    /**
     * @param req
     * @param request
     * @param response
     * @return
     */
    @Override
    public void login(LoginReq req, HttpServletRequest request, HttpServletResponse response) throws IOException{
        try {
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(req.getUsername(),req.getPassword()));
            handleLoginProcess(request, response, authentication);
        } catch (AuthenticationException e) {
            handleLoginProcess(request, response, e);
        }
    }

    /**
     * @param req
     * @return
     */
    @Override
    public Object register(RegisterReq req){
        if(usersRespository.existsByusername(req.getUsername())){
            return RestBean.Code.用户名已存在;
        }
        UsersEntity user=UsersEntity.builder().
                username(req.getUsername()).
                password(passwordEncoder.encode(req.getPassword())).
                realname(req.getRealname()).
                build();

        usersRespository.save(user);

        return RegisterResp.builder().token(JwtUtil.createJWT(JwtUtil.createClaims(req.getUsername()))).build();
    }

    @Override
    public Object getUserInfo(UUID uuid){
        UsersEntity user=usersRespository.findByuuid(uuid);
        if(user==null){
            return RestBean.Code.用户不存在;
        }
        return GetUserInfoResp.builder().
                uuid(user.getUuid()).
                signature(user.getSignature()).
                avatar(user.getAvatar()).
                realname(user.getRealname()).
                role(user.getRole()).
                ceateTime(user.getCeateTime()).
                username(user.getUsername()).
                build();
    }

    @Override
    public Object updateUserAvatar(UUID uuid, MultipartFile avatar){
        UsersEntity user=usersRespository.findByuuid(uuid);
        if(user==null){
            return RestBean.Code.用户不存在;
        }
        String fileName = fileUtil.saveFile(avatar, FileUtil.FileType.AVATAR);
        user.setAvatar(fileName);
        usersRespository.save(user);
        return fileName;
    }
}

